home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 3: CDPD 3
/
Almathera Ten on Ten - Disc 3: CDPD3.iso
/
fish
/
001-100
/
001-025
/
010
/
sq.usq
/
usq.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-17
|
12KB
|
380 lines
/* Program to unsqueeze files formed by sq.com
*
* Useage:
*
* usq [-count] [-fcount] [file1] [file2] ... [filen]
*
* where file1 through filen represent one or more files to be compressed,
* and the following options may be specified:
*
* -count Previewing feature: redirects output
* files to standard output with parity stripped
* and unprintables except CR, LF, TAB and FF
* converted to periods. Limits each file
* to first count lines.
* Defaults to console, but see below how
* to capture all in one file for further
* processing, such as by PIP.
* Count defaults to a very high value.
* No CRC check is performed when previewing.
* Use drive: to cancel this.
*
* -fcount Same as -count except formfeed
* appended to preview of each file.
* Example: -f10.
*
* If no such items are given on the command line you will be
* prompted for commands (one at a time). An empty command
* terminates the program.
*
* The unsqueezed file name is recorded in the squeezed file.
*
*/
/* CHANGE HISTORY:
* 1.3 Close inbuff to avoid exceeding maximum number of
* open files. Includes rearranging error exits.
* 1.4 Add -count option to allow quick inspection of files.
* 1.5 Break up long lines of introductory text
* 1.5 -count no longer appends formfeed to preview of each file.
* -fcount (-f10, -F10) does append formfeed.
* 1.6 Modified to work correctly under MP/M II (DIO.C change) and
* signon message shortened.
* 2.0 Modified to work with CI-C86 compiler (CP/M-86 and MS-DOS)
* 2.1 Modified for use in MLINK
* 2.2 Modified for use with optimizing CI-C86 compiler (MS-DOS)
* 3.0 Generalized for use under UNIX
*
* 3.2 Ported to Amiga & Lattice
* Rick Schaeffer [70120,174] 12/03/85
*/
#include <stdio.h>
#define ERROR -1
/* Definitions and external declarations */
#define RECOGNIZE 0xFF76 /* unlikely pattern */
/* *** Stuff for first translation module *** */
#define DLE 0x90
unsigned int crc; /* error check code */
/* *** Stuff for second translation module *** */
#define SPEOF 256 /* special endfile token */
#define NUMVALS 257 /* 256 data values plus SPEOF*/
#define LARGE 30000
/* Decoding tree */
struct {
int children[2]; /* left, right */
} dnode[NUMVALS - 1];
int bpos; /* last bit position read */
int curin; /* last byte value read */
/* Variables associated with repetition decoding */
int repct; /*Number of times to retirn value*/
int value; /*current byte value or EOF */
#define VERSION "3.2 12/03/85"
/* This must follow all include files */
unsigned int dispcnt; /* How much of each file to preview */
char ffflag; /* should formfeed separate preview from different files */
main(argc, argv)
int argc;
char *argv[];
{
int i,c;
char inparg[16]; /* parameter from input */
dispcnt = 0; /* Not in preview mode */
printf("File unsqueezer version %s (original author: R. Greenlaw)\n\n", VERSION);
/* Process the parameters in order */
for(i = 1; i < argc; ++i)
obey(argv[i]);
if(argc < 2) {
printf("Enter file names, one line at a time, or type <RETURN> to quit.");
do {
printf("\n*");
for(i = 0; i < 16; ++i) {
if((c = getchar()) == EOF)
c = '\n'; /* force empty (exit) command */
if((inparg[i] = c) == '\n') {
inparg[i] = '\0';
break;
}
}
if(inparg[0] != '\0')
obey(inparg);
} while(inparg[0] != '\0');
}
}
/* eject^Leject */
obey(p)
char *p;
{
char *q, cc;
if(*p == '-') {
if(ffflag = ((*(p+1) == 'F') || (*(p+1) == 'f')))
++p;
/* Set number of lines of each file to view */
dispcnt = 65535; /* default */
if(*(p+1))
if((dispcnt = atoi(p + 1)) == 0)
printf("\nBAD COUNT %s", p + 1);
return;
}
/* Check for ambiguous (wild-card) name */
for(q = p; *q != '\0'; ++q)
if(*q == '*' || *q == '?') {
printf("\nCan't accept ambiguous name %s", p);
return;
}
unsqueeze(p);
}
/* eject^Leject */
unsqueeze(infile)
char *infile;
{
FILE *inbuff, *outbuff; /* file buffers */
int i, c;
char cc;
char *p;
unsigned int filecrc; /* checksum */
int numnodes; /* size of decoding tree */
char outfile[128]; /* output file name */
unsigned int linect; /* count of number of lines previewed */
char obuf[128]; /* output buffer */
int oblen; /* length of output buffer */
static char errmsg[] = "ERROR - write failure in %s\n";
if(!(inbuff=fopen(infile, "rb"))) {
printf("Can't open %s\n", infile);
return;
}
/* Initialization */
linect = 0;
crc = 0;
init_cr();
init_huff();
/* Process header */
if(getx16(inbuff) != RECOGNIZE) {
printf("%s is not a squeezed file\n", infile);
goto closein;
}
filecrc = getw16(inbuff);
/* Get original file name */
p = outfile; /* send it to array */
do {
*p = getc(inbuff);
} while(*p++ != '\0');
printf("%s -> %s: ", infile, outfile);
numnodes = getw16(inbuff);
if(numnodes < 0 || numnodes >= NUMVALS) {
printf("%s has invalid decode tree size\n", infile);
goto closein;
}
/* Initialize for possible empty tree (SPEOF only) */
dnode[0].children[0] = -(SPEOF + 1);
dnode[0].children[1] = -(SPEOF + 1);
/* Get decoding tree from file */
for(i = 0; i < numnodes; ++i) {
dnode[i].children[0] = getw16(inbuff);
dnode[i].children[1] = getw16(inbuff);
}
if(dispcnt) {
/* Use standard output for previewing */
putchar('\n');
while(((c = getcr(inbuff)) != EOF) && (linect < dispcnt)) {
cc = 0x7f & c; /* strip parity */
if((cc < ' ') || (cc > '~'))
/* Unprintable */
switch(cc) {
case '\r': /* return */
/* newline will generate CR-LF */
goto next;
case '\n': /* newline */
++linect;
case '\f': /* formfeed */
case '\t': /* tab */
break;
default:
cc = '.';
}
putchar(cc);
next: ;
}
if(ffflag)
putchar('\f'); /* formfeed */
} else {
/* Create output file */
if(!(outbuff=fopen(outfile, "wb"))) {
printf("Can't create %s\n", outfile);
goto closeall;
}
printf("unsqueezing,");
/* Get translated output bytes and write file */
oblen = 0;
while((c = getcr(inbuff)) != EOF) {
crc += c;
obuf[oblen++] = c;
if (oblen >= sizeof(obuf)) {
if(!fwrite(obuf, sizeof(obuf), 1, outbuff)) {
printf(errmsg, outfile);
goto closeall;
}
oblen = 0;
}
}
if (oblen && !fwrite(obuf, oblen, 1, outbuff)) {
printf(errmsg, outfile);
goto closeall;
}
if((filecrc && 0xFFFF) != (crc && 0xFFFF))
printf("ERROR - checksum error in %s\n", outfile);
else printf(" done.\n");
closeall:
fclose(outbuff);
}
closein:
fclose(inbuff);
}
getw16(iob) /* get 16-bit word from file */
FILE *iob;
{
int temp;
temp = getc(iob); /* get low order byte */
temp |= getc(iob) << 8;
if (temp & 0x8000) temp |= (~0) << 15; /* propogate sign for big ints */
return temp;
}
getx16(iob) /* get 16-bit (unsigned) word from file */
FILE *iob;
{
int temp;
temp = getc(iob); /* get low order byte */
return temp | (getc(iob) << 8);
}
/* initialize decoding functions */
init_cr()
{
repct = 0;
}
init_huff()
{
bpos = 99; /* force initial read */
}
/* Get bytes with decoding - this decodes repetition,
* calls getuhuff to decode file stream into byte
* level code with only repetition encoding.
*
* The code is simple passing through of bytes except
* that DLE is encoded as DLE-zero and other values
* repeated more than twice are encoded as value-DLE-count.
*/
int
getcr(ib)
FILE *ib;
{
int c;
if(repct > 0) {
/* Expanding a repeated char */
--repct;
return value;
} else {
/* Nothing unusual */
if((c = getuhuff(ib)) != DLE) {
/* It's not the special delimiter */
value = c;
if(value == EOF)
repct = LARGE;
return value;
} else {
/* Special token */
if((repct = getuhuff(ib)) == 0)
/* DLE, zero represents DLE */
return DLE;
else {
/* Begin expanding repetition */
repct -= 2; /* 2nd time */
return value;
}
}
}
}
/* eject^Leject */
/* Decode file stream into a byte level code with only
* repetition encoding remaining.
*/
int
getuhuff(ib)
FILE *ib;
{
int i;
int bitval;
/* Follow bit stream in tree to a leaf*/
i = 0; /* Start at root of tree */
do {
if(++bpos > 7) {
if((curin = getc(ib)) == ERROR)
return ERROR;
bpos = 0;
/* move a level deeper in tree */
i = dnode[i].children[1 & curin];
} else
i = dnode[i].children[1 & (curin >>= 1)];
} while(i >= 0);
/* Decode fake node index to original data value */
i = -(i + 1);
/* Decode special endfile token to normal EOF */
i = (i == SPEOF) ? EOF : i;
return i;
}